/*
 * 本类作用：mina框架:解码器，用于接收数据时拆包
 * 
 * 作者：袁小杰
 * 博客：http://blog.csdn.net/undoner
 * GIT：https://git.oschina.net/undoner
 * QQ：15137281
 * 
 */
package com.smforj.ssm.mina.codec;
 
import java.nio.charset.Charset;

import org.apache.log4j.Logger;
import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.CumulativeProtocolDecoder;
import org.apache.mina.filter.codec.ProtocolDecoderOutput;

import com.smforj.ssm.mina.server.R;

/***
 * 解码器，用于接收数据时拆包
 * 
 * @author Haijun Gao 
 * @date 2016-7-28 上午8:49:37
 * @desp http://www.cnblogs.com/saga5998/
 * @email 573107773@qq.com
 */
public class MsgDecoder extends CumulativeProtocolDecoder  {

	static Logger log = Logger.getRootLogger();
	 

	private static final int MSGINDEX = 13;
	/***
	 * 消息的最短长度
	 */
	private static final int MSGMINLENGTH = 12;
	private final Charset charset;
	public MsgDecoder() {
		this(Charset.defaultCharset());
	}

	public MsgDecoder(Charset charset) {
		this.charset = charset;
	}
	
	/***
	 * 数据解析
	 */
	@Override
	protected boolean doDecode(IoSession session, IoBuffer in,
			ProtocolDecoderOutput out) throws Exception {   
	    System.out.println("doDecode in.remaining："+in.remaining()); 
	    //当数据内容大于标准时进行解析，否则不进行解析 
	    int length =in.remaining(); 
        if(length >= MSGMINLENGTH){
        	//将所以数据读取到byte数组中
        	byte[] dst = new byte[in.limit()];
        	in.mark();//标记当前位置，以便reset
        	in.get(dst);  
        	byte[] bflag = new byte[12];
        	System.arraycopy(dst, 0, bflag, 0, bflag.length);
        	//读取前12个byte 
        	String sflag = new String(bflag);
        	//人脸识别设备
        	if(R.DIVERFLAG.equals(sflag.trim().toLowerCase()))
        	{ 
        		 //System.out.println("人脸识别");
        		//有数据时，读取4字节判断消息长度
	            byte [] sizeBytes = new byte[4];  
	            //in.mark();//标记当前位置，以便reset  
	            for(int i = 0;i<4;i++)
	            	sizeBytes[i] = in.get(i+MSGINDEX);//读取4字节  
	            int size = MsgUtils.bytesToInt(sizeBytes); 
	            //System.out.println("size : "+size);
	            log.info("size : "+size); 
	            in.reset(); 
	            if(size > in.remaining()){//如果消息内容不够，则重置，相当于不读取size  
	                return false;//父类接收新数据，以拼凑成完整数据  
	            } else{  
	                byte[] bytes = new byte[size];  
	                in.get(bytes, 0, size); 
	              //把字节转换为Java对象的工具类 
	              IoBuffer ioBuffer =IoBuffer.wrap(bytes); 
	      	      byte[] b = new byte [ioBuffer.limit()];   
	      	      ioBuffer.get(b); 
	      	      String pack = new String(b,charset);
	                //String pack = MsgUtils.ioBufferToString(IoBuffer.wrap(bytes)); 
	                out.write(pack); 
	                if(in.remaining() > 0){//如果读取内容后还粘了包，就让父类再重读  一次，进行下一次解析  
	                    return true;  
	                } 
	
	            }  
        	}else if(R.BACKDATA.equals(sflag.trim().toLowerCase()))
        	{
        		log.info(R.BACKDATA+"begin");
        		//有数据时，读取4字节判断消息长度  
        		byte[] blen = new byte[4];
            	System.arraycopy(dst, 12, blen, 0, blen.length); 
	            int size = MsgUtils.bytesToInt(blen);  
	            log.info("size : "+size); 
	            in.reset(); 
	            if(size > in.remaining()){//如果消息内容不够，则重置，相当于不读取size  
	                return false;//父类接收新数据，以拼凑成完整数据  
	            } else{  
	                byte[] bytes = new byte[size];  
	                in.get(bytes, 0, size); 
	       /*       //把字节转换为Java对象的工具类 
	                String pack = MsgUtils.ioBufferToString(IoBuffer.wrap(bytes)); 
	                out.write(pack); 
	                if(in.remaining() > 0){//如果读取内容后还粘了包，就让父类再重读  一次，进行下一次解析  
	                    return true;  
	                } */
	                //把字节转换为Java对象的工具类 
		              IoBuffer ioBuffer =IoBuffer.wrap(bytes); 
		      	      byte[] b = new byte [ioBuffer.limit()];   
		      	      ioBuffer.get(b); 
		      	      String pack = new String(b,charset);
		      	      System.out.println("解码数据："+pack);
		                //String pack = MsgUtils.ioBufferToString(IoBuffer.wrap(bytes)); 
		                out.write(pack); 
		                if(in.remaining() > 0){//如果读取内容后还粘了包，就让父类再重读  一次，进行下一次解析  
		                    return true;  
		                } 
	
	            } 
        	}else
        		in.reset(); 
        	return false;//处理成功，让父类进行接收下个包  
        } 

        return false;//处理成功，让父类进行接收下个包  
	}  
}
